package com.dodo.blog;

import com.comvai.auth.servlet.AuthorizeCallbackServlet;
import com.dodo.blog.exception.PageAlreadyMounted;
import com.dodo.blog.exception.PathAlreadyMounted;
import com.dodo.blog.model.Account;
import com.dodo.blog.ui.page.ErrorPage;
import com.dodo.blog.ui.page.Page;
import com.dodo.blog.ui.page.UnauthorizedPage;
import com.dodo.blog.ui.page.admin.ArticleEdit;
import com.dodo.blog.ui.page.admin.ArticleList;
import com.dodo.blog.ui.page.admin.CategoryEdit;
import com.dodo.blog.ui.page.admin.CategoryList;
import com.dodo.blog.ui.page.admin.PlaygroundEdit;
import com.dodo.blog.ui.page.admin.PlaygroundList;
import com.dodo.blog.ui.page.admin.TagEdit;
import com.dodo.blog.ui.page.admin.TagList;
import com.dodo.blog.ui.page.publish.About;
import com.dodo.blog.ui.page.publish.Articles;
import com.dodo.blog.ui.page.publish.Contact;
import com.dodo.blog.ui.page.publish.Home;
import com.dodo.blog.ui.page.publish.Login;
import com.dodo.blog.ui.page.publish.MyAccount;
import com.dodo.blog.ui.page.publish.Playground;
import com.dodo.blog.ui.page.publish.Portfolio;
import com.dodo.blog.ui.page.publish.Registration;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;

/**
 * @author <a href="mailto:pohorelec@comvai.com">Jozef Pohorelec</a>
 */
public class WebApplication
        implements Serializable
{
    private static final long serialVersionUID = 1L;

    private Map<String, Class<? extends Page>> pageMap = new HashMap<String, Class<? extends Page>>();

    private boolean isDevelopment = false;

    private Logger log = Logger.getLogger( this.getClass().getName() );

    private static WebApplication me;

    public static WebApplication get()
    {
        if ( me == null )
        {
            me = new WebApplication();
        }

        return me;
    }

    private WebApplication()
    {
        init();

        String isDev = System.getProperty( "configuration.development" );
        isDevelopment = Boolean.valueOf( isDev );

        if ( isDevelopment )
        {
            log.warning( "Warning. Application is running in development mode." );
        }
        else
        {
            log.info( "Application is running in deployment mode." );
        }

    }

    public void init()
    {
        // publish
        mount( "/login", Login.class );
        mount( "/registration", Registration.class );
        mount( "/articles/*", Articles.class );
        mount( "/my-account", MyAccount.class );
        mount( "/", Home.class );
        mount( "/playground", Playground.class );
        mount( "/portfolio", Portfolio.class );
        mount( "/contact", Contact.class );
        mount( "/about", About.class );

        // admin
        mount( "/article-list", ArticleList.class );
        mount( "/article-edit", ArticleEdit.class );
        mount( "/tag-list", TagList.class );
        mount( "/tag-edit", TagEdit.class );
        mount( "/category-list", CategoryList.class );
        mount( "/category-edit", CategoryEdit.class );
        mount( "/playground-list", PlaygroundList.class );
        mount( "/playground-edit", PlaygroundEdit.class );
    }

    public void mount( String path, Class<? extends Page> page ) throws PathAlreadyMounted
    {
        if ( pageMap.containsKey( path ) )
        {
            throw new PathAlreadyMounted( "Path has been already mounted with class: " + pageMap.get( path ) );
        }

        if ( pageMap.containsValue( page ) )
        {
            String p = getPathByPageClass( page );
            throw new PageAlreadyMounted( "Page['" + page.getName() + "'] is already mounted for path: " + p );
        }

        pageMap.put( path, page );
    }

    public Class<? extends Page> getPageClassByPath( String path )
    {
        if ( path.equals( "/" ) ) // redirect to custom home page
        {
            return getHomePage();
        }

        for ( Map.Entry<String, Class<? extends Page>> page : pageMap.entrySet() )
        {
            String p = page.getKey();
            if ( p.endsWith( "*" ) )
            {
                if ( path.startsWith( p.replace( "/*", "" ) ) )
                {
                    return page.getValue();
                }
            }
        }

        return pageMap.get( path );
    }

    public String getPathByPageClass( Class<? extends Page> pageClass )
    {
        for ( Map.Entry<String, Class<? extends Page>> item : pageMap.entrySet() )
        {
            if ( item.getValue() == pageClass )
            {
                return item.getKey();
            }
        }

        return null;
    }

    public boolean isDevelopment()
    {
        return isDevelopment;
    }

    public Class<? extends Page> getHomePage()
    {
        return Home.class;
    }

    public Class<? extends Page> getLoginPage()
    {
        return Login.class;
    }

    public Class<? extends ErrorPage> getErrorPage()
    {
        return ErrorPage.class;
    }

    public Class<? extends Page> getUnauthorizedPage()
    {
        return UnauthorizedPage.class;
    }

    public Account getLoggedInAccount()
    {
        return ( Account ) RequestCycle.get().getSession().getAttribute( AuthorizeCallbackServlet.SESSION_AUTH_USER_ATTRIBUTE );
    }

}